package com.wxh.clone;

import java.io.*;

/**
 * @ClassName: CloneUtils
 * @Description: 对象深度克隆：1.序列化 2. 所有引用类型克隆
 * @Author wxh
 * @Date: 2019/9/9 10:50
 * @Version V1.0.0
 * @Since 1.8
 */
public class CloneUtils {

    /**
     * java序列化是指把java对象转换为字节序列的过程，而java反序列化是指把字节序列恢复为java对象的过程
     */
    private CloneUtils(){

    }

    /**
     * 将对象写入内存字节流中，然后从字节流中读取，返回一个新对象
     * 通过java.io.ObjectOutputStream对象输出流的writeObject(Object obj)方法可对参数指定的obj对象进行序列化，
     * 把得到的字节序列写到一个目标输出流中。
     *　通过java.io.ObjectInputStream对象输入流的readObject()方法从一个源输入流中读取字节序列，
     *  再把它们反序列化为一个对象，并将其返回，返回时通过强制类型转换赋值给具体的类对象引用。
     * @param obj
     * @param <T>
     * @return T
     */
    public static <T extends Serializable> T clone(T obj){
        T cloneObj = null;
        try {
            // 写入字节流
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            //  装饰模式
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            // 序列化----写的过程将对象保存到文件或内存中
            oos.writeObject(obj);
            oos.close();
            // 分配内存， 写入原始对象，生成新对象
            // 读取对象内容
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream bis = new ObjectInputStream(bais);
            cloneObj = (T) bis.readObject();
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return cloneObj;
    }


}
